package com.zmn.oms.zmn.business.impl.work;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.oms.business.interfaces.messageV1.app.MessageSendAppService;
import com.zmn.oms.business.interfaces.operator.OrderWorkOperatorBService;
import com.zmn.oms.business.interfaces.orderstock.OrderStockBService;
import com.zmn.oms.business.interfaces.servtype.ServItemBService;
import com.zmn.oms.business.interfaces.xno.OrderXnoBindBService;
import com.zmn.oms.common.annotation.OrderWorkCasOperate;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.TimeUtils;
import com.zmn.oms.constant.MessageQueueTopicConstant;
import com.zmn.oms.model.dto.operator.OrderWorkOperatorDTO;
import com.zmn.oms.model.dto.orderstock.ReleaseStockDTO;
import com.zmn.oms.model.dto.queue.PerfStockWarningDTO;
import com.zmn.oms.model.dto.work.modify.CheckQuotationTypeOrderDTO;
import com.zmn.oms.model.dto.work.modify.OrderUpdateStatusDTO;
import com.zmn.oms.model.dto.work.modify.must.OrderAssignBackDTO;
import com.zmn.oms.model.dto.work.modify.must.OrderWorkGrabDTO;
import com.zmn.oms.model.dto.work.xno.XnoUnBindDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.grab.NonGridGrabOrder;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.query.grab.NonGridGrabOrderQuery;
import com.zmn.oms.model.vo.work.OperatePermissionVO;
import com.zmn.oms.model.vo.work.OrderAssignBackVO;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.fcorderpart.OrderFactoryPartService;
import com.zmn.oms.services.interfaces.grab.NonGridGrabOrderService;
import com.zmn.oms.services.interfaces.wallquotation.WallQuotationService;
import com.zmn.oms.services.interfaces.wallservitem.WallServItemService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.services.interfaces.work.masterwork.MasterWorkService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkAssignBackBService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkGrabBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsCustomWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsDistributeWorkBService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 类描述：工单分单撤回 service
 *
 * @author liuying
 * @date 2019/05/08 18:54
 */
@Slf4j
@Service
public class OrderWorkAssignBackBServiceImpl implements OrderWorkAssignBackBService {

    @Autowired
    private OrderFactoryPartService factoryPartService;
    @Autowired
    private ZsCustomWorkBService zsCustomWorkBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private ZsOrderWorkOperatePermissionBService orderWorkOperatePermissionBService;
    @Autowired
    private OrderChangeRecordService orderChangeRecordService;
    @Autowired
    private MasterWorkService masterWorkService;
    @Autowired
    private OrderXnoBindBService orderXnoBindBService;
    @Autowired
    private ZsOrderWorkBService zsOrderWorkBService;
    @Resource
    private ZmnMQSender zmnMQSender;
    @Resource
    private MessageSendAppService messageSendAppService;
    @Autowired
    private OrderWorkGrabBService orderWorkGrabBService;
    @Autowired
    private ZsDistributeWorkBService zsDistributeWorkBService;
    @Autowired
    private OrderStockBService orderStockBService;
    @Autowired
    private OrderWorkOperatorBService orderWorkOperatorBService;
    @Autowired
    private ServItemBService servItemBService;
    @Autowired
    private NonGridGrabOrderService nonGridGrabOrderService;
    @Resource
    private WallQuotationService wallQuotationService;
    @Resource
    private WallServItemService wallServItemService;

    @Override
    public OrderAssignBackVO getAssignBackVO(Long orderId, Long workId) {

        int count = factoryPartService.countByOrderId(orderId);

        OrderAssignBackVO vo = new OrderAssignBackVO();
        vo.setOrderId(orderId);
        vo.setWorkId(workId);
        vo.setHasFactoryPart(count > 0);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OrderWorkCasOperate(type = OrderConsts.ORDER_OP_TYPE_ASSIGN_BACK)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK, beforeProceed = false)
    public void saveAssignBack(OrderAssignBackDTO assignBackDTO) throws OmsBaseException {

        OperatePermissionVO operatePermission = orderWorkOperatePermissionBService.getOperatePermission(assignBackDTO.getOrderId(), assignBackDTO.getWorkId(), OrderConsts.ORDER_OP_TYPE_ASSIGN_BACK);
        if (!operatePermission.getCanOperate()) {
            throw new OmsBaseException(operatePermission.getMsg());
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(assignBackDTO.getOrderId(), assignBackDTO.getWorkId());
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());

        // 如果工程师属于家修匠
        if (Objects.equals(orderWork.getCompanyId(), CompanyConsts.ZMN_JXJ_COMPANY_ID)) {
            Integer oldServiceItemType = orderWork.getServItemType();
            // 重新判断工单类型
            CheckQuotationTypeOrderDTO checkQuotationTypeOrderDTO = BeanMapper.map(orderWork, CheckQuotationTypeOrderDTO.class);
            checkQuotationTypeOrderDTO.setCompanyId(null);
            checkQuotationTypeOrderDTO.setMasterId(null);
            checkQuotationTypeOrderDTO.setCompatibilityFinalPrice(true);
            Integer newServiceItemType = servItemBService.getServItemType(checkQuotationTypeOrderDTO);
            // servItemType==5的修改成4，并且标识一口价（一口价订单需求兼容app走计价器3.0流程）
            if (Objects.equals(newServiceItemType, OrderConsts.SERVICE_ITEM_TYPE_FINAL_PRICE)) {
                orderWork.setServItemType(OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE);
                orderWork.setFinalPrice(GlobalConsts.YES);
            }else {
                orderWork.setFinalPrice(GlobalConsts.NO);
                orderWork.setServItemType(newServiceItemType);
            }
            log.info("[{}]修改计价类型，旧类型[{}]-->新类型[{}]", orderWork.getWorkId(), oldServiceItemType, newServiceItemType);
        }

        boolean isGrid = zsDistributeWorkBService.isGridDistribute(orderWork);
        // 分单撤回
        this.saveGridAssignBack(orderWork, orderDetail, assignBackDTO, isGrid);

        // 分单撤回，发送库存预警队列
        if (Objects.equals(OrderConsts.ORDER_TYPE_NEW, orderWork.getType()) && NumberUtil.isNotNullOrZero(orderWork.getManageCompanyId())) {
            if (TimeUtils.isCurDateRange(orderWork.getDutyTime(), 14)) {
                PerfStockWarningDTO perfStockWarningDTO = PerfStockWarningDTO.builder()
                        .dutyDate(DateUtil.dateFormatToString(orderWork.getDutyTime(), DateUtil.FORMAT_DEFAULT))
                        .cityId(orderWork.getCityId())
                        .manageCompanyId(orderWork.getManageCompanyId())
                        .servCategId(orderWork.getServCategId())
                        .showCategOneId(orderWork.getShowCategOneId())
                        .showCategTwoId(orderWork.getShowCategId())
                        .build();
                log.info("分单撤回-发送PERF库存预警队列[{}]", perfStockWarningDTO);
                String perfStockWarningJson = JSON.toJSONString(perfStockWarningDTO);
                String perfKey = String.valueOf(orderWork.getWorkId());
                zmnMQSender.send(MessageQueueTopicConstant.ZMN_TOPIC_PERF, MessageQueueTagConsts.ZMN_PERF_STOCK_WARNING, perfKey, perfStockWarningJson);
            }
        }

        // 发送撤回app消息
        Map<String, Object> params = Maps.newHashMap();
        params.put("order_id", String.valueOf(orderWork.getOrderId()));
        params.put("work_id", String.valueOf(orderWork.getWorkId()));
        messageSendAppService.pushAppMessageInfo(MessageConsts.ZMN_MSG_RULEID_BACK, JSON.toJSONString(params),orderWork);

        // 如果是抢单撤回，订单改为指派
        if (Objects.equals(orderWork.getGrabType(), GlobalConsts.YES)) {
            OrderWorkGrabDTO dto = new OrderWorkGrabDTO();
            dto.setGrabType(GlobalConsts.NO);
            dto.setOrderId(assignBackDTO.getOrderId());
            dto.setWorkId(assignBackDTO.getWorkId());
            // 判断是否无网格抢单
            NonGridGrabOrderQuery query = new NonGridGrabOrderQuery();
            query.setOrderId(dto.getOrderId());
            query.setWorkId(dto.getWorkId());
            query.setValidStatus(com.zmn.consts.GlobalConsts.YES);
            List<NonGridGrabOrder> nonGridGrabOrderList = nonGridGrabOrderService.listByQuery(query);
            if (CollectionUtil.isNullOrEmpty(nonGridGrabOrderList)) {
                orderWorkGrabBService.saveGrabType(dto);
            }
        }

        // 释放库存
        ReleaseStockDTO releaseStockDTO = new ReleaseStockDTO();
        releaseStockDTO.setOrderId(orderWork.getOrderId());
        releaseStockDTO.setWorkId(orderWork.getWorkId());
        releaseStockDTO.setMasterId(orderWork.getMasterId());
        releaseStockDTO.setCityId(orderWork.getCityId());
        orderStockBService.releaseStock(releaseStockDTO);

        // 删除墙面报价数据
        wallQuotationService.deleteByKey(assignBackDTO.getWorkId());
        wallServItemService.deleteByWorkId(assignBackDTO.getWorkId());

        // 分单撤回清空责任工程师
        if (!Objects.equals(OrderConsts.ORDER_TYPE_REWORK, orderWork.getType())) {
            orderChangeRecordService.clearCancelLiableAndLiableMasterRecord(orderWork.getOrderId());
        }
    }

    /**
     * 平台直派分单撤回，服务商派单也可使用
     * 不校验按钮状态
     * 不记录分单撤回日志
     * 平台直派不发送库存预警
     * @param assignBackDTO
     * @throws OmsBaseException
     */
    @Override
    public void saveGridAssignBack(OrderWork orderWork, OrderDetail orderDetail, OrderAssignBackDTO assignBackDTO, Boolean isGrid) throws OmsBaseException {
        orderWork.setIsLeave(1);  //1未出发  2已出发

        // 修改师傅出发状态
        masterWorkService.updateMasterLeave(orderWork);

        // 如果已分配师傅解绑小号
        if (!Objects.equals(orderWork.getMasterId(), GlobalConsts.NONE) && Objects.equals(orderDetail.getBindStatus(), OrderConsts.BIND_STATUS_BIND)) {
            // 分单撤回，解绑小号
            XnoUnBindDTO xnoUnBindDTO = new XnoUnBindDTO();
            xnoUnBindDTO.setWorkId(orderWork.getWorkId());
            xnoUnBindDTO.setOrderId(orderWork.getOrderId());
            orderXnoBindBService.unBind(xnoUnBindDTO);
        }

        OrderUpdateStatusDTO orderUpdateConfirmStatusDTO = new OrderUpdateStatusDTO();
        orderUpdateConfirmStatusDTO.setOrderId(assignBackDTO.getOrderId());
        orderUpdateConfirmStatusDTO.setWorkId(assignBackDTO.getWorkId());
        orderUpdateConfirmStatusDTO.setOperatorRemark(assignBackDTO.getOperatorRemark());

        // 已确认状态
        orderUpdateConfirmStatusDTO.setStatus(OrderStatusConsts.WORK_STATUS_CONFIRM);
        orderUpdateConfirmStatusDTO.setOperator(assignBackDTO.getOperator());
        orderUpdateConfirmStatusDTO.setOperatorId(assignBackDTO.getOperatorId());
        zsCustomWorkBService.updateAssignBack(orderUpdateConfirmStatusDTO);

        // 服务商派单，分单撤回清空行政子公司和行政服务商
        if (!isGrid) {
            OrderDetail updateOrderDetail = new OrderDetail();
            updateOrderDetail.setDetailId(orderDetail.getDetailId());
            updateOrderDetail.setGridCompanyId(0);
            updateOrderDetail.setGridCompanyName("");
            updateOrderDetail.setGridManageCompanyId(0);
            updateOrderDetail.setGridManageCompanyName("");
            updateOrderDetail.setUpdater(assignBackDTO.getOperator());
            orderDetailService.updateOrderDetailByKey(updateOrderDetail);

            // 清空行政子公司组织架构
            OrderWorkOperatorDTO dto = BeanMapper.map(assignBackDTO, OrderWorkOperatorDTO.class);
            dto.setGridOrgOneId(0);
            dto.setGridOrgTwoId(0);
            dto.setGridOrgThreeId(0);
            dto.setGridOrgFourId(0);
            orderWorkOperatorBService.insertOrUpdateOperator(dto);
        }

        // 分单撤回重新操作,重置报价及优惠信息
        zsOrderWorkBService.resetQuotationInfo(orderWork);

        // 如果是抢单撤回，订单改为指派
        if (Objects.equals(orderWork.getGrabType(), GlobalConsts.YES)) {
            OrderWorkGrabDTO dto = new OrderWorkGrabDTO();
            dto.setGrabType(GlobalConsts.NO);
            dto.setOrderId(assignBackDTO.getOrderId());
            dto.setWorkId(assignBackDTO.getWorkId());
            // 判断是否无网格抢单
            NonGridGrabOrderQuery query = new NonGridGrabOrderQuery();
            query.setOrderId(dto.getOrderId());
            query.setWorkId(dto.getWorkId());
            query.setValidStatus(com.zmn.consts.GlobalConsts.YES);
            List<NonGridGrabOrder> nonGridGrabOrderList = nonGridGrabOrderService.listByQuery(query);
            if (CollectionUtil.isNullOrEmpty(nonGridGrabOrderList)) {
                orderWorkGrabBService.saveGrabType(dto);
            }
        }

        // 派单撤回清空责任工程师
        if (!Objects.equals(OrderConsts.ORDER_TYPE_REWORK, orderWork.getType())) {
            orderChangeRecordService.clearCancelLiableAndLiableMasterRecord(orderWork.getOrderId());
        }

        // 计价器3.0订单需要清空上门信息
        if (Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)) {
            orderChangeRecordService.clearVisitInfo(assignBackDTO.getOrderId(), assignBackDTO.getWorkId());
        }
    }
}
